// Pipeline Component Library Example
// ----------------------------------
// Colin Bowern (colinbowern@hotmail.com)
// January 2007
//
// Copyright (c) 2007 Colin Bowern
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// * The above copyright notice and this permission notice shall be included in
//   all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#region References
using Microsoft.CommerceServer.Interop;
using Microsoft.CommerceServer.Runtime;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;
#endregion

namespace RockstarGuys.PipelineComponents
{
    /// <summary>
    /// Manages customers order forms.
    /// </summary>
    /// <remarks>
    /// For more information see http://msdn2.microsoft.com/en-us/library/microsoft.commerceserver.runtime.orders.orderform.aspx
    /// </remarks>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1035:ICollectionImplementationsHaveStronglyTypedMembers"), DebuggerDisplay("OrderFormId = {OrderFormId}")]
    public class OrderForm : Dictionary
    {
        #region Fields
        private DictionaryContainer<OrderAddress, IDictionary> addresses;
        private SimpleListContainer<LineItem, IDictionary> lineItems;
        private SimpleListContainer<Payment, IDictionary> payments;
        private SimpleListContainer<PromoCodeRecord, IDictionary> promoCodeRecords;
        private SimpleListContainer<Shipment, IDictionary> shipments;
        private SimpleList<string> basketErrors;
        private SimpleList<string> promoCodes;
        private SimpleList<string> purchaseErrors;
        #endregion

        #region Properties
        #region Simple Collections
        /// <remarks />
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods")]
        public SimpleList<string> BasketErrors
        {
            get
            {
                if (this.basketErrors == null)
                {
                    if (this[OrderForm.KeyNames.BasketErrors] == null)
                    {
                        this[OrderForm.KeyNames.BasketErrors] = new SimpleListClass();
                    }
                    this.basketErrors = new SimpleList<string>((ISimpleList)this[OrderForm.KeyNames.BasketErrors], StringComparer.InvariantCultureIgnoreCase);
                }
                return this.basketErrors;
            }
        }

        /// <remarks />
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods")]
        public SimpleList<string> PromoCodes
        {
            get
            {
                if (this.promoCodes == null)
                {
                    if (this[OrderForm.KeyNames.PromoCodes] == null)
                    {
                        this[OrderForm.KeyNames.PromoCodes] = new SimpleListClass();
                    }
                    this.promoCodes = new SimpleList<string>((ISimpleList)this[OrderForm.KeyNames.PromoCodes], StringComparer.InvariantCultureIgnoreCase);
                }
                return this.promoCodes;
            }
        }

        /// <remarks />
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods")]
        public SimpleList<string> PurchaseErrors
        {
            get
            {
                if (this.purchaseErrors == null)
                {
                    if (this[OrderForm.KeyNames.PurchaseErrors] == null)
                    {
                        this[OrderForm.KeyNames.PurchaseErrors] = new SimpleListClass();
                    }
                    this.purchaseErrors = new SimpleList<string>((ISimpleList)this[OrderForm.KeyNames.PurchaseErrors]);
                }
                return this.purchaseErrors;
            }
        }
        #endregion

        #region Complex Collections
        /// <remarks />
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods"), CLSCompliant(false)]
        public DictionaryContainer<OrderAddress, IDictionary> Addresses
        {
            get
            {
                if (this.addresses == null)
                {
                    if (this[OrderForm.KeyNames.Addresses] == null)
                    {
                        this[OrderForm.KeyNames.Addresses] = new DictionaryClass();
                    }
                    this.addresses = new DictionaryContainer<OrderAddress, IDictionary>((IDictionary)this[OrderForm.KeyNames.Addresses]);
                }
                return this.addresses;
            }
        }

        /// <remarks />
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods"), CLSCompliant(false)]
        public SimpleListContainer<LineItem, IDictionary> LineItems
        {
            get
            {
                if (this.lineItems == null)
                {
                    if (this[OrderForm.KeyNames.LineItems] == null)
                    {
                        this[OrderForm.KeyNames.LineItems] = new SimpleListClass();
                    }
                    this.lineItems = new SimpleListContainer<LineItem, IDictionary>((ISimpleList)this[OrderForm.KeyNames.LineItems]);
                }
                return this.lineItems;
            }
        }

        /// <remarks />
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods"), CLSCompliant(false)]
        public SimpleListContainer<Payment, IDictionary> Payments
        {
            get
            {
                if (this.payments == null)
                {
                    if (this[OrderForm.KeyNames.Payments] == null)
                    {
                        this[OrderForm.KeyNames.Payments] = new SimpleListClass();
                    }
                    this.payments = new SimpleListContainer<Payment, IDictionary>((ISimpleList)this[OrderForm.KeyNames.Payments]);
                }
                return this.payments;
            }
        }

        /// <remarks />
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods"), CLSCompliant(false)]
        public SimpleListContainer<PromoCodeRecord, IDictionary> PromoCodeRecords
        {
            get
            {
                if (this.promoCodeRecords == null)
                {
                    if (this[OrderForm.KeyNames.PromoCodeRecords] == null)
                    {
                        this[OrderForm.KeyNames.PromoCodeRecords] = new SimpleListClass();
                    }
                    this.promoCodeRecords = new SimpleListContainer<PromoCodeRecord, IDictionary>((ISimpleList)this[OrderForm.KeyNames.PromoCodeRecords]);
                }
                return this.promoCodeRecords;
            }
        }

        /// <remarks />
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods"), CLSCompliant(false)]
        public SimpleListContainer<Shipment, IDictionary> Shipments
        {
            get
            {
                if (this.shipments == null)
                {
                    if (this[OrderForm.KeyNames.Shipments] == null)
                    {
                        this[OrderForm.KeyNames.Shipments] = new SimpleListClass();
                    }
                    this.shipments = new SimpleListContainer<Shipment, IDictionary>((ISimpleList)this[OrderForm.KeyNames.Shipments]);
                }
                return this.shipments;
            }
        }
        #endregion

        #region Simple Properties
        /// <remarks />
        public Guid OrderGroupId
        {
            get { return GetGuidFromStringValue(OrderForm.KeyNames.OrderGroupId).Value; }
            set { this[OrderForm.KeyNames.OrderGroupId] = value.ToString(); }
        }

        /// <remarks />
        public Guid OrderFormId
        {
            get { return GetGuidFromStringValue(OrderForm.KeyNames.OrderFormId).Value; }
            set { this[OrderForm.KeyNames.OrderFormId] = value.ToString(); }
        }

        /// <remarks />
        public int CurrencyDecimalPlaces
        {
            get { return GetValue<int>(OrderForm.KeyNames.CurrencyDecimalPlaces); }
            set { this[OrderForm.KeyNames.CurrencyDecimalPlaces] = value; }
        }

        /// <remarks />
        public string TrackingNumber
        {
            get { return this[OrderForm.KeyNames.TrackingNumber] as string; }
            set { this[OrderForm.KeyNames.TrackingNumber] = value; }
        }

        /// <remarks />
        public string Status
        {
            get { return this[OrderForm.KeyNames.Status] as string; }
            set { this[OrderForm.KeyNames.Status] = value; }
        }

        /// <remarks />
        public string BillingAddressId
        {
            get { return this[OrderForm.KeyNames.BillingAddressId] as string; }
            set { this[OrderForm.KeyNames.BillingAddressId] = value; }
        }

        /// <remarks />
        public string PromoUserIdentity
        {
            get { return this[OrderForm.KeyNames.PromoUserIdentity] as string; }
            set { this[OrderForm.KeyNames.PromoUserIdentity] = value; }
        }

        /// <remarks />
        public Guid SoldToId
        {
            get { return GetGuidFromStringValue(OrderForm.KeyNames.SoldToId).Value; }
            set { this[OrderForm.KeyNames.SoldToId] = value.ToString(); }
        }

        /// <remarks />
        public decimal? SubTotal
        {
            get { return GetValue<decimal?>(OrderForm.KeyNames.SubTotal); }
            set { this[OrderForm.KeyNames.SubTotal] = (value.HasValue ? new CurrencyWrapper(value.Value) : null); }
        }

        /// <remarks />
        public decimal? ShippingTotal
        {
            get { return GetValue<decimal?>(OrderForm.KeyNames.ShippingTotal); }
            set { this[OrderForm.KeyNames.ShippingTotal] = (value.HasValue ? new CurrencyWrapper(value.Value) : null); }
        }

        /// <remarks />
        public decimal? HandlingTotal
        {
            get { return GetValue<decimal?>(OrderForm.KeyNames.HandlingTotal); }
            set { this[OrderForm.KeyNames.HandlingTotal] = (value.HasValue ? new CurrencyWrapper(value.Value) : null); }
        }

        /// <remarks />
        public decimal? TaxTotal
        {
            get { return GetValue<decimal?>(OrderForm.KeyNames.TaxTotal); }
            set { this[OrderForm.KeyNames.TaxTotal] = (value.HasValue ? new CurrencyWrapper(value.Value) : null); }
        }

        /// <remarks />
        public decimal? TaxIncluded
        {
            get { return GetValue<decimal?>(OrderForm.KeyNames.TaxIncluded); }
            set { this[OrderForm.KeyNames.TaxIncluded] = (value.HasValue ? new CurrencyWrapper(value.Value) : null); }
        }

        /// <remarks />
        public decimal? Total
        {
            get { return GetValue<decimal?>(OrderForm.KeyNames.Total); }
            set { this[OrderForm.KeyNames.Total] = (value.HasValue ? new CurrencyWrapper(value.Value) : null); }
        }
        #endregion
        #endregion

        #region Constructor
        /// <summary>
        /// Initializes a new instance of the <see cref="OrderForm"/> class.
        /// </summary>
        /// <remarks>
        /// The underlying store can be persisted through referencing the InnerList property.
        /// </remarks>
        public OrderForm() : base()
        {
            this.OrderFormId = Guid.NewGuid();
            this.OrderGroupId = Guid.NewGuid();
            this.BillingAddressId = string.Empty;
            this.Status = string.Empty;
            this.PromoUserIdentity = string.Empty;
            this.SoldToId = Guid.Empty;
            this.CurrencyDecimalPlaces = CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalDigits;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="OrderForm"/> class.
        /// </summary>
        /// <param name="orderGroupId">The order group id.</param>
        /// <param name="orderFormId">The order form id.</param>
        public OrderForm(Guid orderGroupId, Guid orderFormId)
            : base()
        {
            this.OrderGroupId = orderGroupId;
            this.OrderFormId = orderFormId;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="OrderForm"/> class.
        /// </summary>
        /// <param name="container">The container.</param>
        [CLSCompliant(false)]
        public OrderForm(IDictionary container) : base(container) { }
        #endregion

        #region Nested Types
        /// <summary>
        /// Keys used to access the properties in the dictionary.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
        public struct KeyNames
        {
            /// <remarks />
            public const string BasketErrors = "_Basket_Errors";
            /// <remarks />
            public const string PromoCodes = "promo_codes";
            /// <remarks />
            public const string PurchaseErrors = "_Purchase_Errors";
            /// <remarks />
            public const string Addresses = "addresses";
            /// <remarks />
            public const string LineItems = "items";
            /// <remarks />
            public const string Payments = "payments";
            /// <remarks />
            public const string PromoCodeRecords = "promo_code_info";
            /// <remarks />
            public const string Shipments = "shipments";
            /// <remarks />
            public const string OrderGroupId = "BasketOrderGroupId";
            /// <remarks />
            public const string OrderFormId = "orderform_id";
            /// <remarks />
            public const string TrackingNumber = "order_number";
            /// <remarks />
            public const string Status = "orderform_status";
            /// <remarks />
            public const string CurrencyDecimalPlaces = "_currency_decimal_places";
            /// <remarks />
            public const string BillingAddressId = "billing_address_id";
            /// <remarks />
            public const string PromoUserIdentity = "promo_user_identity";
            /// <remarks />
            public const string SoldToId = "user_id";
            /// <remarks />
            public const string SubTotal = "_cy_oadjust_subtotal";
            /// <remarks />
            public const string ShippingTotal = "_cy_shipping_total";
            /// <remarks />
            public const string HandlingTotal = "_cy_handling_total";
            /// <remarks />
            public const string TaxTotal = "_cy_tax_total";
            /// <remarks />
            public const string TaxIncluded = "_cy_tax_included";
            /// <remarks />
            public const string Total = "_cy_total_total";
        }
        #endregion
    }
}
